function fireEvent(element, event){
    if (document.createEventObject){
        // IE浏览器支持fireEvent方法
        var evt = document.createEventObject();
        return element.fireEvent('on'+event,evt)
    }
    else{
        // 其他标准浏览器使用dispatchEvent方法
        var evt = document.createEvent( 'HTMLEvents' );
        // initEvent接受3个参数：
        // 事件类型，是否冒泡，是否阻止浏览器的默认行为
        evt.initEvent(event, true, true);
        return !element.dispatchEvent(evt);
    }
};

// input.hidden.id   = id
// datalist.id       = id__list
// datalist.input.id = id__input
function datalist_change(event) {
    var e = event || window.event;
    var isChrome = window.navigator.userAgent.indexOf("Chrome") !== -1;
    var id = e.currentTarget.id.replace('__input', '');

    // chrome show and input is value; other show is lable input is value;
    var input_value = document.getElementById(id + '__input').value;
    var nodes = document.getElementById(id + '__list').childNodes;
    var setValue = (id, value) => {
        for(var i in nodes) {
            if (nodes[i].nodeName == 'OPTION' && nodes[i].value == value) {
                document.getElementById(id).value = nodes[i].label;
                return true;
            }
        }
        alert("'" + value + "' is Illegal value.");
        var input_id = (id.indexOf("__input") !== -1)? id : id + '__input';

        document.getElementById(input_id).value = '';
        document.getElementById(input_id).focus();
        return false;
    };

    if (isChrome) {
        setValue(id, input_value); // set hidden input value;
    } else {
        document.getElementById(id).value = input_value;
        setValue(id + '__input', input_value);// set input value = label;
    }
    fireEvent(document.getElementById(id), `change`);
}

function create_datalist_options(data) {
    var options = '';
    if (navigator.userAgent.indexOf("Chrome") > -1) {
        var tmp = [];
        Object.keys(data).map((key, i) => {
            tmp[data[key]] = key;
        });
        data = tmp;
    }

    Object.keys(data).map((key, i) => {
        options += `<option label="`+data[key]+`" value="`+key+`" />`;
    });
    return options;
}

function create_datalist(id, opts) {
    var value  = opts.value || '';
    var style  = opts.style ? 'class="'+ opts.style + '"' : '';
    var data   = opts.data || [];
    var tips   = opts.tips || '';
    var name   = opts.name || id;
    var ivalue = data[value]? data[value] : "";

    var html = `<input type="hidden" id="`+id+`" name="`+name+`" value="`+value+`" />` +
               `<input type="text" id="`+id+`__input" list="`+id+`__list" onchange="datalist_change(event)"`+ style +
                     `value="`+ivalue+`" placeholder="`+tips+`"/>` +
               `<datalist id="`+id+`__list">`;

    html += create_datalist_options(data);

    html += "</datalist>";

    return html;
}